--[[
FraidyCatFu - a FuBar plugin for keeping track of who has a fear ward up in your group or raid.

version: 0.2
author: Tabithy
email: tabithy@gmail.com
website: http://www.googlecode.com/p/tabstools
]]

local FEAR_WARD = "Fear Ward"

local tablet = AceLibrary("Tablet-2.0")

FraidyCatFu = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0", "FuBarPlugin-2.0")

FraidyCatFu:RegisterDB("FraidyCatFuDB")
FraidyCatFu:RegisterDefaults('profile', {
	sound=true, text=true, solo=true, group=true, raid=true, battleground=false, arena=false})

local fearWarded = set{}

-- Unit IDs, in table form, so it's easy to iterate over them.
raidUnits = set{}
for i = 1, 40 do
	set.m_add(raidUnits , ("raid" .. i))
end
partyUnits = set{}
for i = 1, 5 do
	set.m_add(partyUnits, ("party" .. i ))
end
playerUnits = set{"player"}

FraidyCatFu.hasIcon = true
FraidyCatFu.cannotDetachTooltip = true
FraidyCatFu.defaultPosition = "RIGHT"

FraidyCatFu.options = {
	type = 'group',
	args = {
		alerts = {
			name="Alerts",
			type='group',
			desc="What type of warnings to use",
			args={
				sound = {
					name="Sound",
					desc="Audible warning",
					type='toggle',
					get=function () return FraidyCatFu.db.profile.sound end,
					set=function (v) FraidyCatFu.db.profile.sound = v end
				},
				text = {
					name="Text",
					desc="Text warning",
					type='toggle',
					get=function () return FraidyCatFu.db.profile.text end,
					set=function(v) FraidyCatFu.db.profile.text = v end
				}
			}
		},
		active = {
			name="Active",
			type='group',
			desc="When to warn about lost fear wards",
			args={
				solo = {
					name="Solo",
					desc="Send warnings when solo",
					type='toggle',
					get=function () return FraidyCatFu.db.profile.solo end,
					set=function (v) FraidyCatFu.db.profile.solo = v end
				},
				group = {
					name="Party",
					desc="Send warnings when in a party",
					type="toggle",
					get=function () return FraidyCatFu.db.profile.party end,
					set=function (v) FraidyCatFu.db.profile.party = v end
				},
				raid = {
					name="Raid",
					desc="Send warnings when in a raid",
					type="toggle",
					get=function () return FraidyCatFu.db.profile.raid end,
					set=function (v) FraidyCatFu.db.profile.raid = v end
				},
				battleground = {
					name="Battleground",
					desc="Send warnings when in a battleground",
					type="toggle",
					get=function () return FraidyCatFu.db.profile.battleground end,
					set=function (v) FraidyCatFu.db.profile.battleground = v end
				},
				arena = {
					name="Arena",
					desc="Send warnings when in an arena",
					type="toggle",
					get=function () return FraidyCatFu.db.profile.arena end,
					set=function (v) FraidyCatFu.db.profile.arena = v end
				}
			}
		}
	}
}
		
FraidyCatFu.OnMenuRequest = FraidyCatFu.options
FraidyCatFu:RegisterChatCommand({"/fraidycatfu"}, FraidyCatFu.options)


function FraidyCatFu:Warn(message)
	RaidNotice_AddMessage(RaidBossEmoteFrame,message , ChatTypeInfo["RAID_WARNING"])
end


function FraidyCatFu:CheckUnit(unit, buff)
	local found = false
	local index = 1
	repeat
		local b = UnitBuff(unit, index)
		found = (b == buff)
		index = index + 1
	until (found or not b) 
	return found
end


function FraidyCatFu:EmitWarning() 
	local party = GetNumPartyMembers()
	local raid = GetNumRaidMembers()
	local type = select(2, IsInInstance())
	return ((type == "pvp" and FraidyCatFu.db.profile.battleground)
		or (type == "arena" and FraidyCatFu.db.profile.arena)
		or (party == 0 and raid == 0 and FraidyCatFu.db.profile.solo)
		or (party > 0 and raid == 0 and not (type == "pvp" or type == "arena") and FraidyCatFu.db.profile.party)
		or (party >0 and raid > 0 and not (type == "pvp" or type == "arena") and FraidyCatFu.db.profile.raid))
end


function FraidyCatFu:WarnPlayer(unit)
	local pronoun = {"their", "his", "her"}
	if FraidyCatFu.db.profile.text then
		if UnitName(unit) then	
			if (unit == "player") then
				self:Warn("You lost your fear ward!")
			else
				self:Warn(UnitName(unit) .. " has lost " .. pronoun[UnitSex(unit)] .. " fear ward!")
			end
		end
	end
	if FraidyCatFu.db.profile.sound then
		PlaySoundFile([[Interface\AddOns\FuBar_FraidyCatFu\alert.wav]])
	end
end


function FraidyCatFu:OnDataUpdate()
	local units
	local warded = set{}
	if (GetNumRaidMembers() > 1) then 
		units = raidUnits
	elseif (GetNumPartyMembers() > 1) then
		units = partyUnits
	else
		units = playerUnits
	end
	for unit in set.elts(units) do
		local name = UnitName(unit)
		if self:CheckUnit(unit, FEAR_WARD) then
			set.m_add(warded, name)
		elseif (fearWarded[name] 
				and not UnitIsDead(unit)
				and not self:CheckUnit(unit, "Spirit of Redemption")
				and self:EmitWarning()) then
			self:WarnPlayer(unit)
		end
	end
	fearWarded = warded
	self:UpdateIcon()
	self:UpdateText()
end


function FraidyCatFu:UpdateIcon()
	if (set.cardinality(fearWarded) == 0) then
		self:SetIcon("no_fear_ward.tga")
	else
		self:SetIcon("has_fear_ward.tga")
	end
end


function FraidyCatFu:OnEnable()
	self:UpdateIcon()
	self:UpdateText()
	self:ScheduleRepeatingEvent("Update", self.Update, 1, self)
end


function FraidyCatFu:OnTooltipUpdate()
	local num = set.cardinality(fearWarded)
	local cat = tablet:AddCategory('columns', 1,
		'child_textR', 1,
		'child_textG', 1,
		'child_textB', 0)
	cat:AddLine('text', "")
	if num > 0 then
		if num == 1 then
			cat:AddLine('text', "one character has a fear ward")
		else
			cat:AddLine('text', num .. " characters have fear wards")
		end
		cat:AddLine('text', "")
		for name in set.elts(fearWarded) do     
			cat:AddLine('text', name, 'textR', 1, 'textG', 1, 'textB', 1)
		end
	else
		cat:AddLine('text', "no characters have fear wards")
	end
end


function FraidyCatFu:OnTextUpdate()
	local cardinality = set.cardinality(fearWarded)
	if (cardinality > 0) then
		self:SetText("" .. cardinality)
	else
		self:SetText("")
	end
end
